package com.example.demo.base.login.service.impl;

import cn.hutool.core.exceptions.ValidateException;
import com.example.demo.base.login.dto.RsaPublicKeyBo;
import com.example.demo.base.login.service.RsaService;
import com.example.demo.exception.ValidatorException;
import com.example.demo.utils.RsaUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.concurrent.TimeUnit;

/**
 * TODO
 *
 * @author mazh47622
 * @date2023/12/18
 * @modify -----------------------------------------------------------------------------------------------------
 * |修改单号|修改人员|修改日期|评审人员|修改说明
 * -----------------------------------------------------------------------------------------------------
 * |      |       |      |       |
 * -----------------------------------------------------------------------------------------------------
 */
@Service
public class RsaServiceImpl implements RsaService {

    private static final String PRIVATE_KEY_ATTRIBUTE_NAME = "rsa_privateKey_%s";

    private static final String PUBLIC_KEY_ATTRIBUTE_NAME = "rsa_publicKey_%s";

    private RedisTemplate<String, String> redisTemplate;

    public RsaServiceImpl(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public RsaPublicKeyBo generateKey() {
        try {
            KeyPair keyPair = RsaUtil.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

            String privateStringKey = RsaUtil.getPrivateKey(privateKey);
            String publicStringKey = RsaUtil.getPublicKey(publicKey);

            String random = RandomStringUtils.randomAlphanumeric(10);
            ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
            valueOperations.set(String.format(PRIVATE_KEY_ATTRIBUTE_NAME, random), privateStringKey, 60,  TimeUnit.SECONDS);

            valueOperations.set(String.format(PUBLIC_KEY_ATTRIBUTE_NAME, random), publicStringKey, 60,  TimeUnit.SECONDS);

            return new RsaPublicKeyBo(publicKey, random, RsaUtil.getPublicKey(publicKey));
        } catch (Exception e) {
            throw new ValidateException("获取rsa秘钥异常");
        }

    }

    @Override
    public String RSADecrypt(String content, String random) {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String privateKeyString = valueOperations.get(String.format(PRIVATE_KEY_ATTRIBUTE_NAME, random));
        if (StringUtils.isEmpty(privateKeyString)){
            throw new ValidatorException("获取私钥失败");
        }
        try {
            content = RsaUtil.decrypt(privateKeyString, content);
        } catch (Exception e) {
            throw new ValidateException("解密失败");
        }

        return content;
    }


    @Override
    public String getPublicKeyByRedis(String random){
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        return  valueOperations.get(String.format(PUBLIC_KEY_ATTRIBUTE_NAME, random));
    }

    @Override
    public String getPrivateKeyByRedis(String random){
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        return  valueOperations.get(String.format(PRIVATE_KEY_ATTRIBUTE_NAME, random));
    }

}
